package org.example.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;

/**
 *   由于springboot在 自动配置的时候设置，如果spring容器里存在WebSecurityConfigurerAdapter就用，没有才会使用默认的，所以如果想自定义就需要 继承WebSecurityConfigurerAdapter并重写方法
 *  继承 WebSecurityConfigurerAdapter， 覆盖configure方法，来进行权限处理
 *
 *   认证流程-
 *   url 发送到springboot应用  ->
 *   请求 被 SpringSecurity的filter拦截，判断是否需要认证->需要认证 就让客户端重定向到 认证界面login ，不许认证直接返回资源
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()    //开启请求权限管理， 要有顺序，放行资源要写在最前面，
                .mvcMatchers("/login.html").permitAll() //放行转到登录页面的请求
                .mvcMatchers("/index").permitAll()  //mvcMatchers匹配请求，permitAll放行请求
                .anyRequest().authenticated()    // anyRequest 任何请求，都进行authenticated权限认证
                .and().formLogin()   //做什么样子的认证，这里是form表单认证
                .loginPage("/login.html") //设置 自定义的登录页面
                .loginProcessingUrl("/doLogin")  //指定处理 登录请求的url
                .usernameParameter("uname")
                .passwordParameter("passwd")
//不适用前后端分离  .successForwardUrl("/index") //认证成功后跳转到的路径   地址不会变 ，   不管之前有没有请求，始终跳转/index
//不适用前后端分离   .defaultSuccessUrl("/index") //认证成功，redirect 跳转的路径 ， 地址会变 ,且可以根据上一次保存的请求优先跳转，如果是在hello页面跳转login登录，登录后会优先跳转之前的hello页面，
                .successHandler(new MyAuthenticationSuccessHandler())  //可用于前后端分离开发，他里面需要传入一个AuthenticationSuccessHandler对象, 该对象主要是设置 登录成功后返回的内容
//不适用前后端分离 .failureForwardUrl("/login.html")  //认证失败之后 forward 跳转    , 能够拿到request作用域的内容
//不适用前后端分离 .failureUrl("/login.html")     //认证失败之后 redirect 跳转 ， 能够拿到 session作用域的内容，   都是获取key 为 SPRING_SECURITY_LAST_EXCEPTION的内容
                .failureHandler(new MyAuthenticationFailureHandler()) //可用于前后端分离，需要传入 一个自定义 认证失败的信息
//不适用前后端分离   .and().logout().logoutUrl("/logout").logoutRequestMatcher(new OrRequestMatcher(new AntPathRequestMatcher("/logout","GET"),
//不适用前后端分离                                                                                   new AntPathRequestMatcher("logout","POST")))  //支持 get、post 的注销请求
//不适用前后端分离  .invalidateHttpSession(true).clearAuthentication(true).logoutSuccessUrl("/login.html")
                .and().logout().logoutSuccessHandler(new MyLogoutSuccessHandler())
                .and().csrf().disable();//禁止 跨站请求保护， 安全考虑
    }
}
